#include "Compile.hpp"
#include "Run.hpp"

class CR
{
public:
    static void RemoveTempFile(const std::string &file_name)
    {
        // 清理文件的个数是不确定的，但是有哪些我们是知道的
        std::string _src = PathUtil::Src(file_name);
        if (FileUtil::isExists(_src))
            unlink(_src.c_str());

        std::string _compiler_error = PathUtil::CompilerError(file_name);
        if (FileUtil::isExists(_compiler_error))
            unlink(_compiler_error.c_str());

        std::string _execute = PathUtil::Exe(file_name);
        if (FileUtil::isExists(_execute))
            unlink(_execute.c_str());

        std::string _stdin = PathUtil::Stdin(file_name);
        if (FileUtil::isExists(_stdin))
            unlink(_stdin.c_str());

        std::string _stdout = PathUtil::Stdout(file_name);
        if (FileUtil::isExists(_stdout))
            unlink(_stdout.c_str());

        std::string _stderr = PathUtil::Stderr(file_name);
        if (FileUtil::isExists(_stderr))
            unlink(_stderr.c_str());
    }
    static std::string signal2Str(int code, const std::string &file_name)
    {
        std::string desc;
        DLOG(DEBUG) << "处理返回值";

        switch (code)
        {
        case 0:
            desc = "编译运行成功";
            break;
        case -1:
            desc = "提交的代码是空";
            break;
        case -2:
            desc = "未知错误";
            break;
        case -3:
            // desc = "代码编译的时候发生了错误";
            util_ns::FileUtil::readFile(PathUtil::CompilerError(file_name), desc, true);
            break;
        case SIGABRT: // 6
            desc = "内存超过范围";
            break;
        case SIGXCPU: // 24
            desc = "CPU使用超时";
            break;
        case SIGFPE: // 8
            desc = "浮点数溢出";
            break;
        default:
            desc = "未知: " + std::to_string(code);
            break;
        }

        return desc;
    }

    // 完成接收客户端Json::Value，处理、运行，然后把标准错误标准输出输出到string
    /* ******************************
     * 客户端发送Json格式：
     * code:
     * stdin:
     * cpu_limit:
     * mem_limit:
     * 服务端输出Json格式：
     * desc:
     * status:
     * stdout:
     * stderr:
     ******************************* */
    static void handle(const std::string &str, std::string &out)
    {
        DLOG(DEBUG) << "进入处理模块";
        Json::Value val;
        Json::Value out_value;
        util_ns::JSON::unserializer(str, val);
        // 处理客户端Json
        const std::string &code = val["code"].asString();
        const std::string &stdin = val["stdin"].asString();
        int cpu_limit = val["cpu_limit"].asInt();
        int mem_limit = val["mem_limit"].asInt();

        DLOG(DEBUG) << "完成消息解析功能";
        const std::string &file_name = util_ns::RandomGuard::GetInstance()->GetRandomNum();
        DLOG(DEBUG) << "获取随机文件名";

        int status_code;
        int signal_num;
        if (code.size() == 0)
        {
            status_code = -1;
            goto END;
        }
        // 生成.cpp in文件，把代码打进去
        if (util_ns::FileUtil::writeFile(util_ns::PathUtil::Src(file_name), code) == false || util_ns::FileUtil::writeFile(util_ns::PathUtil::Stdin(file_name), stdin) == false)
        {
            // 打开文件错误
            status_code = -2;
            goto END;
        }
        // 执行编译运行逻辑
        if (!Compile::compile(file_name))
        {
            status_code = -3;
            goto END;
        }
        signal_num = Runner::Run(file_name, cpu_limit, mem_limit);
        if (signal_num < 0)
        {
            status_code = -2; // 未知错误
        }
        else if (signal_num > 0)
        {
            // 程序运行崩溃了
            status_code = signal_num; // 一并处理
        }
        else
        {
            // 运行成功
            status_code = 0;
        }

        // 以下是输出逻辑
    END:
        out_value["status"] = status_code;
        out_value["desc"] = signal2Str(status_code, file_name);
        if (status_code == 0) // 只有成功了才会整理这些信息，
        {
            // 整个过程全部成功
            std::string _stdout;
            FileUtil::readFile(PathUtil::Stdout(file_name), _stdout, true);
            out_value["stdout"] = _stdout;

            std::string _stderr;
            FileUtil::readFile(PathUtil::Stderr(file_name), _stderr, true);
            out_value["stderr"] = _stderr;
        }
        else
        {
            // 失败了也去读取错误文件中的信息，然后返回
            std::string _stdout;
            FileUtil::readFile(PathUtil::Stdout(file_name), _stdout, true);
            out_value["stdout"] = " ";

            std::string _stderr;
            FileUtil::readFile(PathUtil::CompilerError(file_name), _stderr, true);
            out_value["stderr"] = _stderr;
        }

        util_ns::JSON::serializer(out, out_value);

        RemoveTempFile(file_name);
    }
};